#ifndef system_h
#define system_h

// Source code defines
#define false 0
#define true 1

#define _Verbose_Init_ 0
#define _Kernel_Version_ "v0.00.0000d"

#define Page_Size 0x1000

// The kernel lives in paged-memory at:
#define Higher_Half_Address 0xC00000000
// The kernel's page directory is at:
#define KernelPDAddr 0xFFFFF000 // The last page in memory

// main.c
extern int strlen(const char* str);
extern unsigned char inportb (unsigned short _port);
extern void outportb (unsigned short _port, unsigned char _data);

// vga.c
extern void vga_init();
extern void vga_cls();
extern void vga_movecursor();
extern void vga_setcursor(unsigned char x, unsigned char y);
extern void vga_printchar(unsigned char c);
extern void vga_printstr(unsigned char* str);
extern void vga_settextcolor(unsigned char forecolor, unsigned char backcolor);
extern void vga_setsquare(unsigned char c, unsigned char x, unsigned char y);

// gdt.c
extern void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);
extern void gdt_install();

// idt.c
extern void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags);
extern void idt_install();

// isrs.c
/* This defines what the stack looks like after an ISR was running */
struct regs
{
 unsigned int gs, fs, es, ds;      /* pushed the segs last */
 unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;  /* pushed by 'pusha' */
 unsigned int int_no, err_code;    /* our 'push byte #' and ecodes do this */
 unsigned int eip, cs, eflags, useresp, ss;   /* pushed by the processor automatically */ 
};

// irq.c
extern void irq_install();
extern void irq_install_handler(int irq, void (*handler)(struct regs *r));
extern void irq_uninstall_handler(int irq);

// timer.c
extern void timer_setspeed(int hertz);
extern void timer_handler(struct regs* r);
extern void timer_install();
extern void timer_wait(int ticks);

// kb.c
extern void keyboard_install();
extern void keyboard_handler(struct regs* r);

// mem.c
#define mem_block_size Page_Size
#define mem_num_blocksperentry 32
#define mem_num_blocks (0xFFFFFFFF/mem_block_size)
#define mem_map_entry_size (mem_num_blocksperentry/8)
#define mem_map_num_entries (mem_num_blocks/mem_num_blocksperentry)
#define mem_map_size (mem_map_num_entries*mem_map_entry_size)

extern void mmgr_install();
extern unsigned char* memcpy(unsigned char* dest, const unsigned char* src, int count);
extern unsigned char* memmove(unsigned char* dest, const unsigned char* src, int count);
extern unsigned char* memset(unsigned char* dest, unsigned char val, int count);
extern unsigned short* memsetw(unsigned short* dest, unsigned short val, int count);
extern void mem_displaymapvga();
extern void* mem_findblock();
extern void mem_freeblock(void* p);
extern void paging_install();

// str.c
extern char* itoa(char* str, int num, unsigned char base);

// link.ld
// Remember - the address of these variables indicates the kernel sections, not the value
extern const int code;
extern const int data;
extern const int bss;
extern const int end;

#endif